package bootstrap

import (
	"devops-dcc/configs"
	"devops-dcc/pkg/notifier"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"sync"
)

var (
	cfg          *configs.Config
	db           *gorm.DB
	notifierInst notifier.Notifier
	router       *gin.Engine
	globalLogger *zap.Logger
	initOnce     sync.Once
)

type CleanupFunc func()

func Init() (CleanupFunc, error) {
	var (
		cleanupFuncs []func()
		initErr      error
	)

	initOnce.Do(func() {
		// 1. 加载配置（必须最先执行）
		if err := loadConfig(); err != nil {
			initErr = fmt.Errorf("加载配置失败: %w", err)
			return
		}

		// 2. 初始化日志（其他组件依赖日志）
		if err := InitLogger(); err != nil {
			initErr = fmt.Errorf("初始化日志失败: %w", err)
			return
		}
		cleanupFuncs = append(cleanupFuncs, func() {
			_ = globalLogger.Sync()
		})

		// 3. 初始化数据库
		if initErr = InitDatabase(); initErr != nil {
			initErr = fmt.Errorf("数据库初始化失败: %w", initErr)
			return
		}
		cleanupFuncs = append(cleanupFuncs, func() {
			if sqlDB, err := db.DB(); err == nil {
				_ = sqlDB.Close()
			}
		})

		// 4. 初始化通知器
		if notifierInst, initErr = InitNotifier(); initErr != nil {
			initErr = fmt.Errorf("通知器初始化失败: %w", initErr)
			return
		}

		// 5. 最后初始化路由（确保所有依赖就绪）
		initRoutes()
	})

	return func() {
		// 逆序执行清理
		for i := len(cleanupFuncs) - 1; i >= 0; i-- {
			cleanupFuncs[i]()
		}
	}, initErr
}

// 私有初始化方法
func loadConfig() error {
	var err error
	cfg, err = configs.Load("configs/config.yaml")
	return err
}

// Config 全局访问器（安全访问）
func Config() *configs.Config {
	if cfg == nil {
		panic("config not initialized, call bootstrap.Init() first")
	}
	return cfg
}

func DB() *gorm.DB {
	if db == nil {
		panic("database not initialized, call bootstrap.Init() first")
	}
	return db
}

func Notifier() notifier.Notifier {
	if notifierInst == nil {
		panic("notifier not initialized, call bootstrap.Init() first")
	}
	return notifierInst
}

func Router() *gin.Engine {
	if router == nil {
		panic("router not initialized, call bootstrap.Init() first")
	}
	return router
}

func Logger() *zap.Logger {
	if globalLogger == nil {
		panic("logger not initialized, call bootstrap.Init() first")
	}
	return globalLogger
}
